package com.smsc.headend.connector.bo;

import cn.hutool.core.date.SystemClock;
import com.smsc.headend.connector.builder.AssociationBuilder;
import gurux.dlms.GXDLMSClient;
import gurux.dlms.enums.InterfaceType;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

@Data
@Accessors(chain = true)
@Slf4j
public class AssociationState {
    String deviceAddress;

    Integer roleId;

    Boolean returnPacket;

    GXDLMSClient client;

    Long icSubDataItemId;

    Long lastRequestTime;

    Long lastResponseTime;

    State state;

    String exceptionMsg;

    short frameId;

    AssociationBuilder builder;

    Integer stepNumber;

    Long modelId;

    /**
     * 1 建aa 2:46 超时 release 默认 0
     * @param aaState
     * @return
     */
    public static int needRebuild(AssociationState aaState) {
        if (aaState == null) {
            return 1;
        }

        if (aaState.getClient().getInterfaceType() == InterfaceType.HDLC) {
            // 46的判断aa默认超时2分钟重新建链
            if (aaState.aaTimeUp(2L)) {
                // do 46 release
                return 2;
            }
        }
        return (aaState.getState().equals(AssociationState.State.invalid) || aaState.getState().equals(AssociationState.State.init) ? 1:0);
    }

    public enum State {
        init,
        authorized,
        authorizing,
        invalid
    }

    /**
     * 超过3分钟没有业务报文的request与response时，返回AA超时
     * @return
     */
    public boolean aaTimeUp(Long minValue) {
        if (lastRequestTime != null) {
            boolean res = SystemClock.now() - lastRequestTime >= minValue * 60 * 1000; //default 3min
            if (res) {
                log.info("aa request time up last time {}", lastRequestTime);
                return true;
            }
        }

        if (lastResponseTime != null) {
            boolean res = SystemClock.now() - lastResponseTime >= minValue * 60 * 1000; //default 3min
            if (res) {
                log.info("aa response time up last time {}", lastResponseTime);
                return true;
            }
        }
        return false;
    }
}
